package com.tools.xxf.updatelib.updateapp.fragment;

import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.NetworkUtils;
import com.tools.xxf.updatelib.R;
import com.tools.xxf.updatelib.updateapp.ConfigType;
import com.tools.xxf.updatelib.updateapp.UpdateMode;
import com.tools.xxf.updatelib.updateapp.UpdateProgressListener;
import com.tools.xxf.updatelib.updateapp.UpdateService;

import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.WeakHashMap;

/**
 * TODO 启动下载的Fragment,主要适用于绑定Activity
 *
 * @author XXF
 *         Create Time : 2017/11/3 13:34
 */
public final class UpdateFile extends Fragment {
    private final static String UPDATE_MODEL = "update_model";
    private final static String UPDATE_URL = "update_url";
    private UpdateMode updateModel;
    private String loadUrl;
    private ProgressDialog mProgressDialog;
    private AlertDialog.Builder mLoadMsgDialog;

    private static UpdateFile newInstance(UpdateMode mode, String url, String version) {
        Bundle args = new Bundle();
        UpdateFile fragment = new UpdateFile();
        args.putSerializable(UPDATE_MODEL, mode);
        args.putString(UPDATE_URL, url);
        fragment.setArguments(args);
        return fragment;
    }

    public void show(FragmentManager manager) {
        LogUtils.d("show");
        FragmentTransaction ft = manager.beginTransaction();
        ft.add(this, "UpdateFile");
        ft.commit();
    }

    public static Builder create(String downloadUrl) {
        if (TextUtils.isEmpty(downloadUrl)) {
            throw new NullPointerException("downloadUrl == null");
        }
        return new Builder(downloadUrl);
    }


    public static class Builder {
        private UpdateFile updateFragment;
        private final WeakHashMap<String, Object> UPDATE_CONFIGS = new WeakHashMap<>();

        private Builder(String url) {
            UPDATE_CONFIGS.put(ConfigType.CONFIG_READY.name(), false);
            UPDATE_CONFIGS.put(ConfigType.DOWNLOAD_URL.name(), url);
        }

        public Builder bindModel(UpdateMode mode) {
            UPDATE_CONFIGS.put(ConfigType.LOAD_MODEL.name(), mode);
            UPDATE_CONFIGS.put(ConfigType.CONFIG_READY.name(), true);
            return this;
        }

        /**
         * @param version debug 、develop、release 。
         */
        public Builder versionMode(String version) {
            UPDATE_CONFIGS.put(ConfigType.LOAD_VERSION.name(), version);
            return this;
        }


        private Builder checkConfiguration() {
            final boolean isReady = (boolean) UPDATE_CONFIGS.get(ConfigType.CONFIG_READY.name());
            if (!isReady) {
                throw new RuntimeException("Configuration is not ready,call build method");
            }
            return this;
        }

        @SuppressWarnings({"unchecked"})
        final <T> T getConfigurations(Enum<ConfigType> key) {
            checkConfiguration();
            return (T) UPDATE_CONFIGS.get(key.name());
        }

        public UpdateFile build(FragmentManager manager) {
            if (manager == null) {
                throw new NullPointerException("manager == null");
            }
            UpdateMode mode = getConfigurations(ConfigType.LOAD_MODEL);
            String url = getConfigurations(ConfigType.DOWNLOAD_URL);
            String version = getConfigurations(ConfigType.LOAD_VERSION) + "";
            if (null == updateFragment)
                updateFragment = UpdateFile.newInstance(mode, url, version);
            updateFragment.show(manager);

            return updateFragment;
        }
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LogUtils.d( "onCreate");
        updateModel = (UpdateMode) getArguments().getSerializable(UPDATE_MODEL);
        loadUrl = getArguments().getString(UPDATE_URL);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable
            Bundle savedInstanceState) {

        startServer();//启动服务开启APK下载
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    private void startServer() {
        if (updateModel != null) {
            if (null == mLoadMsgDialog)
                mLoadMsgDialog = new AlertDialog.Builder(getActivity());
            switch (updateModel) {
                case FORCE://用于启动页面强制检测
                    update();
                    LogUtils.d( "绑定服务");
                    break;
                case UNFORCE://用于设置页面用
                    if (UpdateService.isLoading) {
                        AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
                        alertDialog
                                .setMessage(R.string.toast_down_tips)
                                .setPositiveButton("YES", null).show();
                        break;
                    }
                    Toast.makeText(getActivity(), R.string.update_app_model_start, Toast
                            .LENGTH_LONG).show();
                    UpdateService.Builder.create(loadUrl).build(getActivity());
                    LogUtils.d( "启动服务");
                    break;
                default:
                    break;
            }
        } else {
            LogUtils.d( "updateModel IS  empty");
        }
    }

    public void update() {
        if (null == mProgressDialog) {
            mProgressDialog = new ProgressDialog(getActivity());
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);// 设置水平进度条
            mProgressDialog.setCancelable(false);// 设置是否可以通过点击Back键取消
            mProgressDialog.setCanceledOnTouchOutside(false);// 设置在点击Dialog外是否取消Dialog进度条
            mProgressDialog.setMax(100);
            mProgressDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
                @Override
                public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                    if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent
                            .ACTION_DOWN) {
                        mLoadMsgDialog.setPositiveButton("OK", new DialogInterface
                                .OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                if (getActivity() != null) {
                                    getActivity().finish();
                                }
                                System.exit(0);
                                System.gc();
                            }
                        }).setNegativeButton("CANCLE", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        }).setMessage("Make sure to cancel update and close it ?");
                        mLoadMsgDialog.show();
                    }
                    return false;
                }
            });
        }
        Intent bindIntent = new Intent(getActivity(), UpdateService.class);
        bindIntent.putExtra("downloadUrl", loadUrl);
        getActivity().bindService(bindIntent, mConnection, Context.BIND_AUTO_CREATE);
    }

    private UpdateService.LocalBinder serviceBinder;

    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            serviceBinder = ((UpdateService.LocalBinder) service);
            serviceBinder.setUpdateProgressListener(new UpdateProgressListener() {

                @Override
                public void start() {
                    LogUtils.d( "start=");
                }

                @Override
                public void update(int progress) {
                    LogUtils.d("progress=" + progress);
                    if (mProgressDialog != null) {
                        if (!mProgressDialog.isShowing()) {
                            mProgressDialog.show();
                        }
                        mProgressDialog.setProgress(progress);
                    }
                }

                @Override
                public void success() {
                    LogUtils.d( "success=");
                    if (mProgressDialog != null) {
                        if (mProgressDialog.isShowing()) {
                            mProgressDialog.hide();
                        }
                    }
                    if (getActivity() != null)
                        getActivity().finish();
                }

                @Override
                public void error(Exception e) {
                    getActivity().unbindService(mConnection);
                    if (mProgressDialog != null) {
                        if (mProgressDialog.isShowing()) {
                            mProgressDialog.hide();
                        }
                    }
                    String msg = "";

                    if (e instanceof SocketException) {
                        msg = "Network connection interrupt,try again ?";
                    } else if (e instanceof SocketTimeoutException) {
                        msg = "Timeout error,,try again ?";
                    } else if (e instanceof NullPointerException) {
                        msg = "update error ,,try again ?";
                    } else {
                        msg = "Unknown exception ,try again ?";
                    }
                    if (!NetworkUtils.isConnected()) {
                        msg = "Connection exception , try again?";
                    }
                    mLoadMsgDialog.setPositiveButton("OK", new DialogInterface
                            .OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            UpdateFile.this.update();
                        }
                    }).setNegativeButton("CANCLE", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            getActivity().finish();
                            System.exit(0);
                            System.gc();
                        }
                    }).setMessage(msg);
                    mLoadMsgDialog.show();
                }
            });
        }

        public void onServiceDisconnected(ComponentName className) {
            LogUtils.d( "onServiceDisconnected=");
// Received when the service unexpectedly disconnects.
            serviceBinder = null;
        }
    };

    @Override
    public void onDestroy() {
        super.onDestroy();
        LogUtils.d( "onDestroy" + updateModel.name());
        if (updateModel == UpdateMode.FORCE && mConnection != null) {
            LogUtils.d("onDestroy 服务");
            getActivity().unbindService(mConnection);
        }
        if (null != mProgressDialog)
            mProgressDialog.dismiss();
        mProgressDialog = null;
        mLoadMsgDialog = null;
    }
}
